package org.example.new_hbps_backend_reconstruction.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.example.new_hbps_backend_reconstruction.common.results.R;
import org.example.new_hbps_backend_reconstruction.entity.HeartRateLogsEntity;
import org.example.new_hbps_backend_reconstruction.entity.PatientDeviceEntity;
import org.example.new_hbps_backend_reconstruction.entity.PersureHeartRateEntity;
import org.example.new_hbps_backend_reconstruction.mapper.PatientDeviceMapper;
import org.example.new_hbps_backend_reconstruction.service.HeartRateLogsService;
import org.example.new_hbps_backend_reconstruction.service.PatientDeviceService;
import org.example.new_hbps_backend_reconstruction.service.PersureHeartRateService;
import org.example.new_hbps_backend_reconstruction.utils.HTTPUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

@Service
@Slf4j
public class PatientDeviceServiceImpl extends
        ServiceImpl<PatientDeviceMapper, PatientDeviceEntity> implements PatientDeviceService {

    @Value("${hardware.url}")
    private String hardwareUrl;

    @Autowired
    private HTTPUtils httpUtils;

    @Autowired
    private HeartRateLogsService heartRateLogsService;

    @Autowired
    private PersureHeartRateService persureHeartRateService;

    @Override
    public R addPatientDevice(PatientDeviceEntity patientDevice) {
        // 检测该用户是否已经绑定该设备
        LambdaQueryWrapper<PatientDeviceEntity> wrapper = new LambdaQueryWrapper<>();
        PatientDeviceEntity tmp = new PatientDeviceEntity();
        tmp.setDeviceUid(patientDevice.getDeviceUid());
        wrapper.setEntity(tmp);
        PatientDeviceEntity one = this.getOne(wrapper.last("limit 1"));
        if (one != null) {
            return R.failed("该设备正在被他人使用,无法绑定");
        }
        // 设置最后一次更新时间默认为当前时间
        patientDevice.setLastUpdateTime(LocalDateTime.now());
        return R.ok(this.save(patientDevice));
    }

    // 异常回滚事务
    @Transactional(rollbackFor = Exception.class)
    @Override
    public R syncDeviceData(PatientDeviceEntity patientDevice) {
        //  根据设备id和患者id补全字段
        LambdaQueryWrapper<PatientDeviceEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.setEntity(patientDevice);
        patientDevice = this.getOne(wrapper.last("limit 1"));
        //	查询从最后一次同步时间到当前时间的 血压数据，心率数据
        JSONObject data = new JSONObject();
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        data.put("mac", patientDevice.getDeviceUid());
        data.put("start_time", dtf.format(patientDevice.getLastUpdateTime()));
        data.put("end_time", dtf.format(LocalDateTime.now()));
        //	 获取血压数据
        try {
            JSONObject post = httpUtils.post(hardwareUrl + "/getblood", data);
            JSONArray dataList = post.getJSONArray("data");
            if (dataList != null) {
                // 批量插入血压数据库
                // 重构数据
                List<PersureHeartRateEntity> persureHeartRateEntities = new ArrayList<>();
                for (int i = 0; i < dataList.size(); i++) {
                    JSONObject jsonObjectTmp = dataList.getJSONObject(i);
                    PersureHeartRateEntity tmp = new PersureHeartRateEntity();
                    tmp.setPatientUid(patientDevice.getPatientUid());
                    tmp.setSystolic(
                            Float.valueOf(jsonObjectTmp.getJSONObject("Sbp").getInteger("Int64")));
                    tmp.setDiastolic(Float.valueOf(jsonObjectTmp.getJSONObject("Dbp").getInteger(
                            "Int64")));
                    // note: 添加特定占位符使用‘x’指定字符串即可
                    DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'");
                    tmp.setUploadTime(LocalDateTime.parse(jsonObjectTmp.getJSONObject(
                            "Time").getString("Time"), df));
                    persureHeartRateEntities.add(tmp);
                }
                persureHeartRateService.AddPressureInBatches(persureHeartRateEntities);
            }
        } catch (Exception e) {
            // 手动强制回滚事务，这里一定要第一时间处理
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            log.error("同步血压数据失败", e);
            return R.failed("同步血压数据失败");
        }

        //  插入心率数据库中，完成批量查询操作
        try {
            JSONObject post = httpUtils.post(hardwareUrl + "/getheartrate", data);
            JSONArray dataList = post.getJSONArray("data");
            if (dataList != null) {
                // 批量查询心率数据，插入数据库
                // 重构数据
                List<HeartRateLogsEntity> heartRateLogsEntities = new ArrayList<>();
                for (int i = 0; i < dataList.size(); i++) {
                    JSONObject jsonObjectTmp = dataList.getJSONObject(i);
                    HeartRateLogsEntity tmp = new HeartRateLogsEntity();
                    tmp.setPatientUid(patientDevice.getPatientUid());
                    tmp.setHeartRate(jsonObjectTmp.getJSONObject("Hr").getInteger("Int64"));
                    // note: 添加特定占位符使用‘x’指定字符串即可
                    DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'");
                    tmp.setUploadTime(LocalDateTime.parse(jsonObjectTmp.getJSONObject(
                            "Time").getString("Time"), df));
                    heartRateLogsEntities.add(tmp);
                }
                heartRateLogsService.saveBatch(heartRateLogsEntities);
            }
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            log.error("同步心率数据失败", e);
            return R.failed("同步心率数据失败");
        }
        //	没有错误则需要更新最后一次上传时间
        patientDevice.setLastUpdateTime(LocalDateTime.now());
        //	更新
        this.updateById(patientDevice);
        return R.ok();
    }

    @Override
    public R unbindDevice(PatientDeviceEntity patientDevice) {
        // 检测该用户是否已经绑定该设备
        LambdaQueryWrapper<PatientDeviceEntity> wrapper = new LambdaQueryWrapper<>();
        PatientDeviceEntity tmp = new PatientDeviceEntity();
        tmp.setDeviceUid(patientDevice.getDeviceUid());
        tmp.setPatientUid(patientDevice.getPatientUid());
        wrapper.setEntity(tmp);
        PatientDeviceEntity one = this.getOne(wrapper.last("limit 1"));
        if (one == null) {
            return R.failed("该设备未被绑定");
        }
        return R.ok(this.remove(wrapper));
    }
}